package ui;

import control.Control;
import ui.actionhandler.RowFocusAdaptor;
import ui.actionhandler.RowMouseAdaptor;
import ui.dnd.DragAndDropTransferHandler;
import ui.dnd.DraggableMouseListener;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: Deshun
 * Date: 2/14/13
 * Time: 11:20 AM
 * To change this template use File | Settings | File Templates.
 */
public class FormRow extends JPanel implements Transferable {
    //TODO remove static counter, border and number label from the adjustment tab when debug is over.

    List<FormRowCell> controlList;
    private int maxCells;
    static int counter = 0;

    private int rowNumber;
    private int idealHeight;
    private int idealWidth;
    private boolean draggable;
    private FormPanel parent;
//    private JPanel panel;

    private JLabel addItemButton;
    private JLabel adjustmentTab;

    FormRow(FormPanel formPanel) {
        super(new BorderLayout());
//        startTime = System.currentTimeMillis();
        counter++;
        setOpaque(false);
        controlList = new ArrayList<FormRowCell>();
        addItemButton = new JLabel();
        adjustmentTab = new JLabel(Integer.toString(counter));
        parent = formPanel;
        idealHeight = 75;
        idealWidth = 200;

        java.net.URL imageURL = this.getClass().getClassLoader().getResource("images/add.png");
        ImageIcon addIcon = new ImageIcon(imageURL);
        addItemButton.setIcon(addIcon);

        addItemButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                requestToolbar();
            }
        });

//        getPanel().addMouseListener(new RowMouseAdaptor());
//        getPanel().addFocusListener(new RowFocusAdaptor());
        getPanel().addMouseListener(new DraggableMouseListener());
        getPanel().setTransferHandler(new DragAndDropTransferHandler());

//        adjustmentTab.setMinimumSize(new Dimension(10, getIdealHeight()));
        adjustmentTab.setBackground(Color.gray);
        this.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
//                System.out.println("Component resized " +(System.currentTimeMillis() - startTime));
                System.out.println("Resized "+ getSize());
            }
        });
    }

    Component explode() {
        if ( getComponentCount() > 0 ) {
            removeAll();
        }

        JPanel controls = new JPanel(new FlowLayout(FlowLayout.LEADING));
        controls.setOpaque(false);
//        setPreferredSize(new Dimension(getIdealWidth(), getIdealHeight()));

        for ( FormRowCell currentCell : controlList ) {
            controls.add(currentCell.explode());
        }

        JPanel addItem = new JPanel();
        addItem.setOpaque(false);
        addItem.add(addItemButton, BorderLayout.CENTER);

        add(adjustmentTab, BorderLayout.WEST);
        add(controls, BorderLayout.CENTER);
        add(addItem, BorderLayout.EAST);
//        System.out.println("Row exploded "+ (System.currentTimeMillis() - startTime)+ " milli seconds after row creation" );
//        System.out.println(getWidth());
//        System.out.println(getHeight());
        return this;
    }
//    long startTime;

    public void paint(Graphics g) {
        super.paint(g);
//        System.out.println("Row painted "+ ( System.currentTimeMillis() - startTime)+ " milli seconds after row creation" );
        if ( ( getWidth() <= 0 ) || ( getHeight() <= 0 ) ) {
            System.out.println("width or height not set");
            return;
        }
//        System.out.println(getWidth());
//        System.out.println(getHeight());
        setIdealWidth(getWidth());

    }

    void addControl(Control control) {
        control.setPositionInRow(controlList.size());
        control.setRow(this);
//        updateDimension(control.getIdealWidth(), control.getIdealHeight());
        controlList.add(new FormRowCell(control));
        //Might have to find a neater way
        if ( popupMenu != null && popupMenu.isVisible() ) {
            hideToolbar();
        }
        revalidate();
    }

    //lets say row 1 2 3 are filled
    // when removing row 1's control
    // row 2 and row 3 will move up to take their row. this cause an error when removing the controls later
    // also the rows won't not be displayed accurately there after.
    void removeControl(Control control) {
        if ( controlList.isEmpty() ) {
            System.out.println(" there is no cells in this row");
        } else {
            controlList.remove(control.getPositionInRow());
//        updateDimension();
            reassignPosition();

        }
    }

    void reassignPosition() {
        int position = 0;
        for ( FormRowCell currentCell : controlList ) {
            currentCell.setPositionInRow(position++);
        }
    }

    //TODO height and width need to be calculated in a more flexible way. There should be a limit to width and height need to change depending on the arrangement within the row
    @Deprecated
    void updateDimension(int width, int height) {
        this.idealWidth += width;
        if ( this.idealHeight < height )
            this.idealHeight = height;
    }

    @Deprecated
    void updateDimension() {
        idealHeight = 75;
        idealWidth = 200;

        for ( FormRowCell currentCell : controlList ) {
            updateDimension(currentCell.getIdealWidth(), currentCell.getIdealHeight());
        }

    }

    public int getIdealHeight() {
        return idealHeight;
    }

    public void setIdealHeight(int height) {
        this.idealHeight = height;
    }

    public int getIdealWidth() {
        return idealWidth;
    }

    public void setIdealWidth(int width) {
        this.idealWidth = width;
    }

    JPopupMenu popupMenu;
    public void requestToolbar() {
        popupMenu = new JPopupMenu();
        popupMenu.setOpaque(false);
        Component toolbar = getParent1().requestToolbar(this);
        popupMenu.add(toolbar);
        popupMenu.show(this.getPanel(), 0, ( int ) ( idealHeight - toolbar.getPreferredSize().getHeight() ) / 2);

    }

    public void hideToolbar() {
        popupMenu.setVisible(false);
        this.explode();
    }

    public FormPanel getParent1() {
        return parent;
    }

    public void setParent(FormPanel parent) {
        this.parent = parent;
    }

    @Override
    public DataFlavor[] getTransferDataFlavors() {
        DataFlavor[] flavors = {null};

        try {
            flavors[0] = FormPanel.getDragAndDropRowDataFlavor();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            return null;
        }

        return flavors;
    }

    @Override
    public boolean isDataFlavorSupported(DataFlavor flavor) {

        DataFlavor[] flavors = {null};

        try {
            flavors[0] = FormPanel.getDragAndDropRowDataFlavor();
        } catch (Exception ex ) {
            System.out.println(ex.getMessage());
            return false;
        }

        for (DataFlavor f : flavors) {
            if(f.equals(flavor))
                return true;
        }

        return false;
    }

    @Override
    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
        DataFlavor thisFlavor = null;

        try {
            thisFlavor = FormPanel.getDragAndDropRowDataFlavor();
        } catch (Exception ex ) {
            System.out.println(ex.getMessage());
            return null;
        }

        if(thisFlavor != null && flavor.equals(thisFlavor)) {
            return FormRow.this;
        }

        return null;
    }

    public JPanel getPanel() {
        return this;
    }

    public boolean isEmpty() {
        if ( controlList.size() == 0 ) {
            return true;
        }
        return false;
    }

    public int getRowNumber() {
        return rowNumber;
    }

    public void setRowNumber(int rowNumber) {
        this.rowNumber = rowNumber;
        for ( FormRowCell currentControl : controlList ) {
            currentControl.setRow(rowNumber);
        }
    }

    public int getMaxCells() {
        return maxCells;
    }

    public void setMaxCells(int maxCells) {
        this.maxCells = maxCells;
    }
}
